package com.koo.common.utils.secret;

import com.koo.common.exception.RRException;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.*;

/**
 * 加密工具类
 * @author chalrin
 * @Date 2022
 */
public class AESUtil {
    private static final String AES = "AES";
    private static final String CRYPT_KEY = "kl2f_hjkd.md345i";
    public static boolean initialized = false;

    public AESUtil() {
    }

    public static void main(String[] args) {
        String value = "com.mysql.jdbc.Driver";
        String idEncrypt = encrypt(value);
        System.out.println("加密后:  " + idEncrypt);
        String idDecrypt = decrypt(idEncrypt);
        System.out.println("解密后:  " + idDecrypt);
    }



    /**
     * AES解密
     * @param content 密文
     */
    public static byte[] decrypt(byte[] content, byte[] keyByte, byte[] ivByte) throws InvalidAlgorithmParameterException {
        initialize();
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
            Key sKeySpec = new SecretKeySpec(keyByte, "AES");

            cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte));// 初始化
            byte[] result = cipher.doFinal(content);
            return result;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (NoSuchProviderException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void initialize(){
        if (initialized) return;
        Security.addProvider(new BouncyCastleProvider());
        initialized = true;
    }
    //生成iv
    public static AlgorithmParameters generateIV(byte[] iv) throws Exception{
        AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
        params.init(new IvParameterSpec(iv));
        return params;
    }

    public static byte[] encrypt(byte[] src, String key) throws Exception {
        Cipher cipher = Cipher.getInstance("AES");
        SecretKeySpec securekey = new SecretKeySpec(key.getBytes(), "AES");
        cipher.init(1, securekey);
        return cipher.doFinal(src);
    }

    public static byte[] decrypt(byte[] src, String key) throws Exception {
        Cipher cipher = Cipher.getInstance("AES");
        SecretKeySpec securekey = new SecretKeySpec(key.getBytes(), "AES");
        cipher.init(2, securekey);
        return cipher.doFinal(src);
    }

    public static String byte2hex(byte[] b) {
        String hs = "";
        String stmp = "";

        for(int n = 0; n < b.length; ++n) {
            stmp = Integer.toHexString(b[n] & 255);
            if (stmp.length() == 1) {
                hs = hs + "0" + stmp;
            } else {
                hs = hs + stmp;
            }
        }

        return hs.toUpperCase();
    }

    public static byte[] hex2byte(byte[] b) {
        if (b.length % 2 != 0) {
            throw new IllegalArgumentException("长度不是偶数");
        } else {
            byte[] b2 = new byte[b.length / 2];

            for(int n = 0; n < b.length; n += 2) {
                String item = new String(b, n, 2);
                b2[n / 2] = (byte)Integer.parseInt(item, 16);
            }

            return b2;
        }
    }

    public static final String decrypt(String data) {
        return decrypt(data, "kl2f_hjkd.md345i");
    }

    public static final String decrypt(String data, String cryptKey) {
        if (cryptKey != null && cryptKey.length() == 16) {
            try {
                return new String(decrypt(hex2byte(data.getBytes()), cryptKey));
            } catch (Exception var3) {
                return null;
            }
        } else {
            throw new RRException("密码必须为16位");
        }
    }

    public static final String encrypt(String data) {
        return encrypt(data, "kl2f_hjkd.md345i");
    }

    public static final String encrypt(String data, String cryptKey) {
        if (cryptKey != null && cryptKey.length() == 16) {
            try {
                return byte2hex(encrypt(data.getBytes(), cryptKey));
            } catch (Exception var3) {
                return null;
            }
        } else {
            throw new RRException("密码必须为16位");
        }
    }
}
